//WeakMap结构与Map结构类似， 也是用于生成键值对的集合。
// WeakMap 可以使用 set 方法添加成员
const wm1 = new WeakMap();
const key = {
	foo: 1
};
wm1.set(key, 2);
wm1.get(key) // 2
// WeakMap 也可以接受一个数组，
// 作为构造函数的参数
const k1 = [1, 2, 3];
const k2 = [4, 5, 6];
const wm2 = new WeakMap([
	[k1, 'foo'],
	[k2, 'bar']
]);
wm2.get(k2) // "bar"


/*
WeakMap与Map的区别有两点。

首先，WeakMap只接受对象作为键名（null除外），不接受其他类型的值作为键名。
*/

const map = new WeakMap();
map.set(1, 2)
// TypeError: 1 is not an object!
map.set(Symbol(), 2)
// TypeError: Invalid value used as weak map key
map.set(null, 2)
// TypeError: Invalid value used as weak map key




/*

其次，WeakMap的键名所指向的对象，不计入垃圾回收机制。
WeakMap的设计目的在于，有时我们想在某个对象上面存放一些数据，但是这会形成对于这个对象的引用。请看下面的例子。

*/

const e1 = document.getElementById('foo');
const e2 = document.getElementById('bar');
const arr = [
	[e1, 'foo 元素'],
	[e2, 'bar 元素'],
];
//一旦不再需要这两个对象， 我们就必须手动删除这个引用， 否则垃圾回收机制就不会释放e1和e2占用的内存。
// 不需要 e1 和 e2 的时候
// 必须手动删除引用  这样的写法显然很不方便。一旦忘了写，就会造成内存泄露。
arr[0] = null;
arr[1] = null;



/*
WeakMap 就是为了解决这个问题而诞生的，它的键名所引用的对象都是弱引用，即垃圾回收机制不将该引用考虑在内。
因此，只要所引用的对象的其他引用都被清除，垃圾回收机制就会释放该对象所占用的内存。
也就是说，一旦不再需要，WeakMap 里面的键名对象和所对应的键值对会自动消失，不用手动删除引用。

基本上，如果你要往对象上添加数据，又不想干扰垃圾回收机制，就可以使用 WeakMap。
一个典型应用场景是，在网页的 DOM 元素上添加数据，就可以使用WeakMap结构。
当该 DOM 元素被清除，其所对应的WeakMap记录就会自动被移除。
*/

const wm = new WeakMap();
const element = document.getElementById('example');
wm.set(element, 'some information');
wm.get(element) // "some information"

/*
上面代码中，先新建一个 WeakMap 实例。然后，将一个 DOM 节点作为键名存入该实例，并将一些附加信息作为键值，一起存放在 WeakMap 里面。
这时，WeakMap 里面对element的引用就是弱引用，不会被计入垃圾回收机制。
也就是说，上面的 DOM 节点对象除了 WeakMap 的弱引用外，其他位置对该对象的引用一旦消除，该对象占用的内存就会被垃圾回收机制释放。
WeakMap 保存的这个键值对，也会自动消失。
总之，WeakMap的专用场合就是，它的键所对应的对象，可能会在将来消失。WeakMap结构有助于防止内存泄漏。
注意，WeakMap 弱引用的只是键名，而不是键值。键值依然是正常引用。
*/

const wm = new WeakMap();
let key = {};
let obj = {
	foo: 1
};

wm.set(key, obj);
obj = null;
wm.get(key)
// Object {foo: 1}
